require "tools/bitwise.lua"

DvString = {}
function DvString:stringSplit(str, step)
  local start = 1
  local nSplitIndex = 1
  local nSplitArray = {}
  while true do
    local nFindLastIndex = string.find(str, step, start)
    if not nFindLastIndex then
      nSplitArray[nSplitIndex] = string.sub(str, start, string.len(str))
      break
    end
    nSplitArray[nSplitIndex] = string.sub(str, start, nFindLastIndex - 1)
    start = nFindLastIndex + string.len(step)
    nSplitIndex = nSplitIndex + 1
  end
  return nSplitArray
end
function DvString:stringSplitWityByte(str, byte)
  local posarray = {}
  local alllen = #str
  for var = 1, alllen do
    local charstr = str[var]
    if string.byte(str, var) == byte then
      table.insert(posarray, var)
    end
  end
  local splitarray = {}
  local splitpos = 1
  for var = 1, #posarray do
    local pos = posarray[var]
    if tonumber(pos) >= splitpos - 1 then
      local str = string.sub(str, splitpos, pos - 1)
      table.insert(splitarray, str)
    end
    splitpos = pos + 1
  end
  if splitpos <= #str then
    table.insert(splitarray, string.sub(str, splitpos, #str))
  end
  return splitarray
end
function DvString:stringSplitForSqlite(str, col, row)
  local start = 1
  local nSplitIndex = 1
  local nSplitArray = {}
  if string.len(str) <= 0 then
    return nSplitArray
  end
  while true do
    local nFindLastIndex = string.find(str, row, start)
    if not nFindLastIndex then
      break
    end
    local nColArray = {}
    local nColIdx = 1
    local colStart = 1
    local colstr = string.sub(str, start, nFindLastIndex - 1)
    while true do
      local colLastIndex = string.find(colstr, col, colStart)
      if not colLastIndex then
        nColArray[nColIdx] = string.sub(colstr, colStart, string.len(colstr))
        break
      end
      nColArray[nColIdx] = string.sub(colstr, colStart, colLastIndex - 1)
      colStart = colLastIndex + string.len(col)
      nColIdx = nColIdx + 1
    end
    nSplitArray[nSplitIndex] = nColArray
    start = nFindLastIndex + string.len(row)
    nSplitIndex = nSplitIndex + 1
  end
  return nSplitArray
end
function DvString:formatFillIn(str, strlist)
  local retrunstr = str
  for var = 1, #strlist do
    local str = strlist[var]
    retrunstr = string.gsub(retrunstr, "{" .. var .. "}", "" .. str)
  end
  return retrunstr
end
function DvString:subDvString(sName, nMaxCount, nShowCount, isomit)
  if isomit == nil then
    isomit = false
  end
  if sName == nil or nMaxCount == nil then
    return
  end
  local sStr = sName
  local tCode = {}
  local tName = {}
  local nLenInByte = #sStr
  local nWidth = 0
  if nShowCount == nil then
    nShowCount = nMaxCount - 3
  end
  for i = 1, nLenInByte do
    local curByte = string.byte(sStr, i)
    local byteCount = 0
    if curByte > 0 and curByte <= 127 then
      byteCount = 1
    elseif curByte >= 192 and curByte < 223 then
      byteCount = 2
    elseif curByte >= 224 and curByte < 239 then
      byteCount = 3
    elseif curByte >= 240 and curByte <= 247 then
      byteCount = 4
    end
    local char
    if byteCount > 0 then
      char = string.sub(sStr, i, i + byteCount - 1)
      i = i + byteCount - 1
    end
    if byteCount == 1 then
      nWidth = nWidth + 1
      table.insert(tName, char)
      table.insert(tCode, 1)
    elseif byteCount > 1 then
      nWidth = nWidth + 2
      table.insert(tName, char)
      table.insert(tCode, 2)
    end
  end
  if nMaxCount < nWidth then
    local _sN = ""
    local _len = 0
    for i = 1, #tName do
      _sN = _sN .. tName[i]
      _len = _len + tCode[i]
      if nShowCount <= _len then
        break
      end
    end
    if isomit then
      sName = _sN .. "..."
    else
      sName = _sN
    end
  end
  return sName
end
function DvString:trim(s)
  return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
function DvString:trimLeft(s)
  return string.gsub(s, "^%s+", "")
end
function DvString:trimRight(s)
  return string.gsub(s, "%s+$", "")
end
function SubUTF8DvString(s, n)
  local dropping = string.byte(s, n + 1)
  if not dropping then
    return s
  end
  if dropping >= 128 and dropping < 192 then
    return SubUTF8DvString(s, n - 1)
  end
  return string.sub(s, 1, n)
end
function DvString:t_S2T(_szText)
  function stack_newStack()
    local first = 1
    local last = 0
    local stack = {}
    local m_public = {}
    function m_public.pushBack(_tempObj)
      last = last + 1
      stack[last] = _tempObj
    end
    function m_public.temp_getBack()
      if m_public.bool_isEmpty() then
        return nil
      else
        local val = stack[last]
        return val
      end
    end
    function m_public.popBack()
      stack[last] = nil
      last = last - 1
    end
    function m_public.bool_isEmpty()
      if first > last then
        first = 1
        last = 0
        return true
      else
        return false
      end
    end
    function m_public.clear()
      while false == m_public.bool_isEmpty() do
        stack.popFront()
      end
    end
    return m_public
  end
  function getVal(_szVal)
    local s, e = string.find(_szVal, "\"", 1, string.len(_szVal))
    if nil ~= s and nil ~= e then
      return string.sub(_szVal, 2, string.len(_szVal) - 1)
    else
      return tonumber(_szVal)
    end
  end
  local m_szText = _szText
  local charTemp = string.sub(m_szText, 1, 1)
  if "{" == charTemp then
    m_szText = string.sub(m_szText, 2, string.len(m_szText))
  end
  function doS2T()
    local tRet = {}
    local tTemp
    local stackOperator = stack_newStack()
    local stackItem = stack_newStack()
    local val = ""
    while true do
      local dLen = string.len(m_szText)
      if dLen <= 0 then
        break
      end
      charTemp = string.sub(m_szText, 1, 1)
      if "[" == charTemp or "=" == charTemp then
        stackOperator.pushBack(charTemp)
        m_szText = string.sub(m_szText, 2, dLen)
      elseif "\"" == charTemp then
        local s, e = string.find(m_szText, "\"", 2, dLen)
        if nil ~= s and nil ~= e then
          val = val .. string.sub(m_szText, 1, s)
          m_szText = string.sub(m_szText, s + 1, dLen)
        else
          return nil
        end
      elseif "]" == charTemp then
        if "[" == stackOperator.temp_getBack() then
          stackOperator.popBack()
          stackItem.pushBack(val)
          val = ""
          m_szText = string.sub(m_szText, 2, dLen)
        else
          return nil
        end
      elseif "," == charTemp then
        if "=" == stackOperator.temp_getBack() then
          stackOperator.popBack()
          local Item = stackItem.temp_getBack()
          Item = getVal(Item)
          stackItem.popBack()
          if nil ~= tTemp then
            tRet[Item] = tTemp
            tTemp = nil
          else
            tRet[Item] = getVal(val)
          end
          val = ""
          m_szText = string.sub(m_szText, 2, dLen)
        else
          return nil
        end
      elseif "{" == charTemp then
        m_szText = string.sub(m_szText, 2, string.len(m_szText))
        local t = doS2T()
        if nil ~= t then
          szText = sz_T2S(t)
          tTemp = t
        else
          return nil
        end
      elseif "}" == charTemp then
        m_szText = string.sub(m_szText, 2, string.len(m_szText))
        return tRet
      elseif " " ~= charTemp then
        val = val .. charTemp
        m_szText = string.sub(m_szText, 2, dLen)
      else
        m_szText = string.sub(m_szText, 2, dLen)
      end
    end
    return tRet
  end
  local t = doS2T()
  return t
end

local function unicode_to_utf8(convertStr)
    if type(convertStr)~="string" then
        return convertStr
    end

    local resultStr=""
    local i=1
    
    while true do
        local num1=string.byte(convertStr,i)
        local unicode
        if num1~=nil and string.sub(convertStr,i,i+1)=="\\u" then
            unicode=tonumber("0x"..string.sub(convertStr,i+2,i+5))
            i=i+6
        elseif num1~=nil then
            unicode=num1
            i=i+1
        else
            break
        end


        print(unicode)
        if unicode <= 0x007f then
            resultStr=resultStr..string.char(bit.band(unicode,0x7f))
        elseif unicode >= 0x0080 and unicode <= 0x07ff then
            resultStr=resultStr..string.char(bit.bor(0xc0,bit.band(bit.rshift(unicode,6),0x1f)))
            resultStr=resultStr..string.char(bit.bor(0x80,bit.band(unicode,0x3f)))
        elseif unicode >= 0x0800 and unicode <= 0xffff then
            resultStr=resultStr..string.char(bit.bor(0xe0,bit.band(bit.rshift(unicode,12),0x0f)))
            resultStr=resultStr..string.char(bit.bor(0x80,bit.band(bit.rshift(unicode,6),0x3f)))
            resultStr=resultStr..string.char(bit.bor(0x80,bit.band(unicode,0x3f)))
        end
    end
    resultStr=resultStr..'\0'
    print(resultStr)
    return resultStr

end


local function utf8_to_unicode(convertStr)
    if type(convertStr)~="string" then
       return convertStr
    end

    local resultStr=""
    local i=1
    local num1=string.byte(convertStr,i)
    
    while num1~=nil do
        print(num1)
        local tempVar1,tempVar2
        
        if num1 >= 0x00 and num1 <= 0x7f then
            tempVar1=num1
            tempVar2=0
        elseif bit.band(num1,0xe0)== 0xc0 then
            local t1 = 0
            local t2 = 0
            t1 = bit.band(num1,bit.rshift(0xff,3))
            i=i+1
            num1=string.byte(convertStr,i)
            t2 = bit.band(num1,bit.rshift(0xff,2))
            tempVar1=bit.bor(t2,bit.lshift(bit.band(t1,bit.rshift(0xff,6)),6))
            tempVar2=bit.rshift(t1,2)
        elseif bit.band(num1,0xf0)== 0xe0 then
            local t1 = 0
            local t2 = 0
            local t3 = 0

            t1 = bit.band(num1,bit.rshift(0xff,3))
            i=i+1
            num1=string.byte(convertStr,i)
            t2 = bit.band(num1,bit.rshift(0xff,2))
            i=i+1
            num1=string.byte(convertStr,i)
            t3 = bit.band(num1,bit.rshift(0xff,2))
            tempVar1=bit.bor(bit.lshift(bit.band(t2,bit.rshift(0xff,6)),6),t3)
            tempVar2=bit.bor(bit.lshift(t1,4),bit.rshift(t2,2))
        end
        
        resultStr=resultStr..string.format("\\u%02x%02x",tempVar2,tempVar1)
        print(resultStr)

        i=i+1
        num1=string.byte(convertStr,i)
    end
    
    print(resultStr)
    return resultStr

end
